#!/bin/bash
# CPU使用率过高故障修复脚本（无邮件通知版）
# 适用于已检测到CPU负载过高的情况
# 知识图谱关联配置 - 与故障节点ID对应
FIX_CODE_ID="CPU-FULL-001"  # 对应知识图谱中"CPU使用率过高（负载过高）"故障ID


# 配置参数
PROCESS_THRESHOLD=50      # 单个进程CPU使用率阈值(%)
MAX_PROCESSES=5           # 一次最多处理的进程数量
LOG_FILE="/var/log/fix_high_cpu.log"
WHITELIST_PROCESSES=("init" "systemd" "kernel" "sshd" "bash" "system" "docker" "kubelet")  # 系统关键进程白名单

# 初始化日志
log() {
    local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
    echo "[$timestamp] $1" >> $LOG_FILE
    echo "[$timestamp] $1"  # 同时输出到控制台
}

# 获取当前CPU使用率
get_current_cpu_usage() {
    local usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
    echo "$usage"
}

# 获取高CPU占用的进程列表
get_high_cpu_processes() {
    # 获取CPU使用率超过阈值的进程，排除内核进程和白名单进程
    ps -eo pid,user,%cpu,cmd --sort=-%cpu | awk -v threshold=$PROCESS_THRESHOLD '$3 > threshold {print}' | while read -r pid user cpu cmd; do
        local is_whitelisted=0
        for process in "${WHITELIST_PROCESSES[@]}"; do
            if echo "$cmd" | grep -q "$process"; then
                is_whitelisted=1
                break
            fi
        done
        if [ $is_whitelisted -eq 0 ] && [ $pid -ne $$ ]; then  # 排除脚本自身
            echo "$pid $user $cpu $cmd"
        fi
    done | head -n $MAX_PROCESSES
}

# 处理高CPU占用进程
handle_high_cpu_processes() {
    local initial_usage=$(get_current_cpu_usage)
    log "开始处理高CPU负载问题，初始CPU使用率: $initial_usage%"
    
    local processes=$(get_high_cpu_processes)
    
    if [ -z "$processes" ]; then
        log "未发现CPU使用率超过 $PROCESS_THRESHOLD% 的进程"
        return 0
    fi
    
    log "检测到高CPU占用进程：\n$processes\n处理措施："
    
    # 逐行处理进程
    echo "$processes" | while read -r pid user cpu cmd; do
        log "发现高CPU占用进程: PID=$pid, USER=$user, CPU=$cpu%, COMMAND=$cmd"
        
        # 首先尝试发送SIGSTOP暂停进程，然后SIGCONT恢复
        log "尝试暂停并恢复进程 $pid"
        kill -STOP $pid 2>/dev/null
        sleep 2
        kill -CONT $pid 2>/dev/null
        
        # 检查进程是否仍然高CPU占用
        local new_cpu=$(ps -p $pid -o %cpu --no-headers 2>/dev/null)
        if [ -n "$new_cpu" ] && (( $(echo "$new_cpu > $PROCESS_THRESHOLD" | bc -l) )); then
            # 如果仍然高占用，发送SIGTERM尝试优雅终止
            log "进程 $pid 仍然高CPU占用，尝试优雅终止"
            kill -TERM $pid 2>/dev/null
            sleep 5
            
            # 检查进程是否已终止
            if ps -p $pid > /dev/null; then
                # 如果仍然运行，发送SIGKILL强制终止
                log "进程 $pid 未能优雅终止，尝试强制终止"
                kill -KILL $pid 2>/dev/null
                log "进程 $pid ($cmd) 已强制终止 (原CPU: $cpu%)"
            else
                log "进程 $pid ($cmd) 已优雅终止 (原CPU: $cpu%)"
            fi
        else
            log "进程 $pid ($cmd) 已恢复正常CPU占用 (原CPU: $cpu%, 现CPU: $new_cpu%)"
        fi
    done
    
    # 记录处理后的CPU使用率
    local final_usage=$(get_current_cpu_usage)
    log "处理后CPU使用率: $final_usage%"
    log "CPU负载处理完成"
    
    echo "初始CPU使用率: $initial_usage%"
    echo "处理后CPU使用率: $final_usage%"
}

# 主函数
main() {
    log "CPU高负载修复脚本启动"
    handle_high_cpu_processes
}

# 启动主函数
main
